package com.ruoyi.common.utils.file;
import java.util.List;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;

public class Filedownload {
    public static HttpURLConnection http(String urls, String method){
        try {
            HttpURLConnection http = (HttpURLConnection) new URL(urls).openConnection();
            http.setRequestMethod(method);
//			http.setDoOutput(true);
//			http.setDoInput(true);
            http.setConnectTimeout(1000*60);
            http.setReadTimeout(1000*60);
//			http.setRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
//			http.setRequestProperty("Accept-Encoding","gzip, deflate, br");
//			http.setRequestProperty("Accept-Language","zh-CN,zh;q=0.9,ja;q=0.8,en;q=0.7");
//			http.setRequestProperty("Cache-Control","max-age=0");
            http.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
            return http;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }


    private static boolean isrange = false;
    private static long range = 0,all = 0;
    //private static ForkJoinPool pools = new ForkJoinPool(Runtime.getRuntime().availableProcessors());

    public static void thread_download(JTextArea pane, Integer number, String... line){
        try {
            File desktop = FileSystemView.getFileSystemView().getHomeDirectory();
            File log_file = new File(desktop,"data.log");
            RandomAccessFile log = new RandomAccessFile(log_file,"rwd");
            if(log_file.length()>0){String url = log.readUTF();range = log.readLong();all = log.readLong();if(url!=null && range>0 && all>0){
                System.out.println("url "+url);
                System.out.println("range "+range);
                System.out.println("all "+all);
                line = new String[]{url};isrange = true;}}
            for (String urls : line) {
                String filename = urls.substring(urls.lastIndexOf("/")+1);
                HttpURLConnection http = http(urls,"GET");
                if(isrange){
                    http.setRequestProperty("Range", "bytes=" + range + "-" + all);
                }
                if(!String.valueOf(http.getResponseCode()).matches("(206|200)")){
                    continue;
                }
                long content_length = http.getContentLengthLong();
                File file = new File(desktop,filename);
                if(!file.exists()){
                    RandomAccessFile raf = new RandomAccessFile(file,"rwd");
                    raf.setLength(content_length);
                    raf.close();}
                long blockSize = content_length / number;
                CompletableFuture<?>[] future = new CompletableFuture[number];
                AtomicLong array = new AtomicLong(0);
                CompletableFuture.runAsync(()->{
                    try {
                        while(true){
                            log.seek(0);
                            log.writeUTF(urls);
                            log.writeLong(isrange?array.get()+range:array.get());
                            log.writeLong(isrange?all:content_length);
                            long last_size = array.get();
                            TimeUnit.SECONDS.sleep(1);
                            long now = array.get(),length = now - last_size;
                            long second = (content_length - now)/(length==0?1:length);
                            String timer = String.format("%02d:%02d:%02d",second/3600,second%3600/60,second%60);
                            boolean is_size;
                            double size = (is_size = length>1024*1024)?length/1024d/1024d:length/1024d;
                            String time = String.format("%.2f "+(is_size?"MB/S":"KB/S"),size);
                            long now1 = isrange?now+range:now,length1 = isrange?all:content_length;
                            pane.setText(String.format("名称:%s%n大小:%d/%dMB 进度:%d%% 速度:%s 时间:%s",
                                    filename,
                                    (int)((isrange?array.get()+range:array.get())/1024d/1024d),
                                    (int)((isrange?all:content_length)/1024d/1024d),
                                    (int)Math.ceil(100d*now1/length1),
                                    time,
                                    timer));
                            if(array.get()>=content_length){
                                break;
                            }
                        }
                        log.close();
                        log_file.delete();
                        isrange = false;
                        range = all = 0;
                        System.err.println("文件删除");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
                for (int threadId = 1; threadId <= number; threadId++) {
                    long index = threadId;
                    long startIndex = isrange?range+(threadId - 1) * blockSize:(threadId - 1) * blockSize;
                    AtomicLong endIndex = new AtomicLong(startIndex + blockSize - 1);
                    if(threadId == number){
                        endIndex.set(isrange?all:content_length);
                    }
                    System.err.println("线程" + threadId + "下载:" + startIndex + "字节~" + endIndex.get() + "字节");
                    future[threadId - 1] = CompletableFuture.runAsync(()->{
                        try{
                            HttpURLConnection http2 = http(urls,"GET");
                            http2.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex.get());
                            if(http2.getResponseCode()!=206){
                                return;
                            }
                            InputStream is = http2.getInputStream();//返回资源
                            RandomAccessFile raf2 = new RandomAccessFile(file,"rwd");
                            raf2.seek(startIndex);
                            byte[] buffer = new byte[1024*200];
                            int len=0;
                            while((len = is.read(buffer))!=-1){raf2.write(buffer,0,len);array.set(array.get()+len); }
                            is.close();
                            raf2.close();
                            System.err.println("线程 "+index+" 完成");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    });
                }
                CompletableFuture.allOf(future).join();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static Thread download_thread = null;
    private static volatile int down_status = 1;


    public static void main(String[] args) throws Exception {
        JDialog jdialog = new JDialog();
        jdialog.setTitle("文件下载");
        jdialog.setLayout(new FlowLayout(FlowLayout.CENTER,0,100));
        jdialog.setAlwaysOnTop(true);
        jdialog.setSize(600,500);
        jdialog.setResizable(false);
        jdialog.setLocationRelativeTo(null);
        jdialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        //System.out.println("我是呵呵哈哈哈".replaceAll("(.)\\1+","$1"));
        JPopupMenu menu = new JPopupMenu("系统提示");
        JTextArea pane = new JTextArea();
        pane.setLineWrap(true);
        pane.setComponentPopupMenu(menu);
        pane.setFont(new Font("微软雅黑",Font.PLAIN,18));
        pane.setPreferredSize(new Dimension(550,300));
        ActionListener action = e->{
            JMenuItem menus = (JMenuItem)e.getSource();
            String text = pane.getSelectedText();
            switch (menus.getText()) {
                case "开始下载":
                    System.out.println("text "+text);
                    if(text == null || !text.matches("https?://(.+?)")){JOptionPane.showMessageDialog(jdialog,"URL地址错误!","系统提示",JOptionPane.INFORMATION_MESSAGE);break;
                    }CompletableFuture.runAsync(()->thread_download(pane,4,text));
                    break;
                case "继续下载":
                    menus.setText("暂停下载");
                    //if(pools.isShutdown())pools = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
                    CompletableFuture.runAsync(()->thread_download(pane,4,text));
                    break;
                case "暂停下载":
                    menus.setText("继续下载");
                    //if(!pools.isShutdown())pools.shutdownNow();
                    break;
            }
        };
        Stream.of("开始下载","暂停下载","继续下载").forEach(a->{
            JMenuItem item = new JMenuItem(a);
            menu.add(item);
            item.setFont(new Font("黑体",Font.BOLD,18));
            item.addActionListener(action);
        });
        jdialog.add(pane);
        jdialog.setVisible(true);

        //new Thread(()->JOptionPane.showMessageDialog(pane,pane,"系统提示!",JOptionPane.INFORMATION_MESSAGE)).start();
        new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE, new DropTargetAdapter()
        {
            @Override
            public void drop(DropTargetDropEvent dtde)
            {
                try {
                    if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                        dtde.dropComplete(true);
                        @SuppressWarnings("unchecked")
                        List<File> list = (List<File>)dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
                        for (File file : list){
                            System.out.println(file);
                            if(!file.getName().endsWith(".txt")){
                                continue;
                            }
                            String[] line = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8)
                                    .stream().filter(a->a.matches("https?://(.+?)")).toArray(String[]::new);
                            if(line.length<1){JOptionPane.showMessageDialog(jdialog,"NO URLS","系统提示",JOptionPane.INFORMATION_MESSAGE);continue;}
                            thread_download(pane,2,line);
                        }
                    }else {
                        dtde.rejectDrop();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        //BaseTools.text_lists("D:\\桌面\\test");
        //System.out.println("hj \"4545 455\" kl".replaceAll("(?<=\") (?<!\")","00"));
//		Matcher patter2 = Pattern.compile("[A-Z]{1}[a-z]+ (\\w+)",Pattern.DOTALL).matcher("Astring name");
//		while(patter2.find())System.out.println(patter2.group(1));
        //System.out.println(Arrays.toString(WebMvcConfig.class.getClasses()));
//		Files.copy(new URL("https://cdn.staticfile.org/vue/3.2.36/vue.global.min.js")
//				.openStream(),Paths.get("E:\\qwer\\qwer14\\NettyServer\\src\\main\\resources\\static\\vue.global.min.js"));

    }
}
